#include <iostream>
#include <string>
#include <cstdlib>
#include <vector>
#include <unistd.h>
#include <ctime>
#include "task.hpp"

using namespace std;


enum
{
    UsageError= 1,
    ArgError,
    PipeError
};
void Usage(const std::string &proc)
{
    cout<<"Usage:"<<proc<<"sub_process_num"<<endl;
}
//用一个类封装管道
class Channel
{
public:
    Channel(int wfd,pid_t sub_id,const std::string &name)//构造
        :_wfd(wfd)
        ,_sub_process_id(sub_id)
        ,_name(name)
        {}
    void PrintDebug()
    {
        cout << "_wfd: " << _wfd;
        cout << ",_sub_process_id: " << _sub_process_id;
        cout << ", _name: " << _name << endl;
    }
    string name() {return _name;}
    int wfd() {return _wfd;}
    pid_t pid() { return _sub_process_id; }
    ~Channel()//析构
    {
    }

private:
    int _wfd;//父进程通过此向channel写东西
    pid_t _sub_process_id;//记录子进程
    string _name;//channel名字
};

//将冗长的创建子进程封装一下
class ProcessPool
{
public:
    ProcessPool(int sub_process_num) //构造
        : _sub_process_num(sub_process_num)
    {}
    int CreateProcess(work_t work) // 回调函数
    {
        for (int number = 0; number < _sub_process_num; number++)
        {
            int pipefd[2]{0};
            int n = pipe(pipefd);
            if (n < 0)
                return PipeError;

            pid_t id = fork();
            if (id == 0)
            {
                // child -> r
                close(pipefd[1]);
                // 执行任务
                dup2(pipefd[0], 0);
                work();
                exit(0);
            }
            string cname = "channel-" + to_string(number);
            // father
            close(pipefd[0]);
            channels.push_back(Channel(pipefd[1], id, cname));
        }
        return 0;
    }
    int NextChannel()
    {
        static int next = 0;
        int c = next;
        next++;
        next %= channels.size();
        return c;
    }
    void SendTaskCode(int index, uint32_t code)
    {
        cout << "send code: " << code << " to " << channels[index].name() << " sub prorcess id: " <<  channels[index].pid() << endl;
        write(channels[index].wfd(), &code, sizeof(code));
    }
    void Debug()
    {
        for (auto &channel : channels)
        {
            channel.PrintDebug();
        }
    }
    ~ProcessPool()
    {
    }

private:
    int _sub_process_num;
    vector<Channel> channels;
};


int main(int argc ,char* argv[])
{
    if(argc!=2)
    {
        Usage(argv[0]);
        return UsageError;
    }

    int sub_process_num = std::stoi(argv[1]);//把进程数转整型
    if(sub_process_num == 0)
        return ArgError;

    //vector<Channel> channels;
    //把所有的channel(管道)push到vector中，那么对管道的管理就会变成对vector的增删查改
    //create process
    // for(int num=0;num<sub_process_num;num++)
    // {
    //     int pipefd[2]{0};
    //     int n = pipe(pipefd);
    //     if(n<0)
    //         return PipeError;
    //     pid_t id = fork();
    //     if(id == 0)//子进程
    //     {
    //         close(pipefd[1]);
    //         sleep(1);
    //         exit(0);
    //     }
    //     string cname = "channel-"+to_string(num);
    //     //父进程
    //     close(pipefd[0]);
    //     channels.push_back(Channel(pipefd[1],id,cname));
    // }
    ProcessPool *proc_ptr = new ProcessPool(sub_process_num);
    proc_ptr->CreateProcess(worker);
    //控制子进程
    // for(auto& e:channels)
    // {
    //     e.PrintDebug();
    // }
    while(1)
    {
        // a. 选择一个进程和通道
        int channel = proc_ptr->NextChannel();
        // cout << channel.name() << endl;

        // b. 你要选择一个任务
        uint32_t code = NextTask();

        // c. 发送任务
        proc_ptr->SendTaskCode(channel, code);

        sleep(1);
    }

    //回收、等待子进程
    delete proc_ptr;
    return 0;
}